﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace Acoris.Document
{
    using Acoris.Content;

    /// <summary>
    /// 表示一个资源字典
    /// </summary>
    public sealed class ResourceDictionary:
        IDictionary<Guid,ResourceKey>,IEnumerable<KeyValuePair<Guid,ResourceKey>>
    {        
        internal Dictionary<Guid,ResourceKey> m_resourceKey;
        internal IContentResourceFactory m_contentFactory;
        private object m_lock;

        internal ResourceDictionary(IContentResourceFactory factory)
        {
            m_lock = new object();
            m_resourceKey = new Dictionary<Guid, ResourceKey>();
            m_contentFactory = factory ?? throw new ArgumentNullException();
        }

        #region Method

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T LoadResource<T>(ResourceKey key)
        {
            return m_contentFactory.LoadResource<T>(key);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void SaveResource<T>(ResourceKey key,T value)
        {
            m_contentFactory.SaveResource<T>(key, value);
        }

        /// <summary>
        /// 将指定的键值添加到当前字典
        /// </summary>
        /// <param name="key">要添加的键</param>
        /// <param name="value">要添加的值</param>
        public void Add(Guid key, ResourceKey value)
        {
            lock (m_lock) {
                if (!ContainsKey(key)) {
                    m_resourceKey.Add(key, value);
                }
            }
        }

        /// <summary>
        /// 将指定的键值对添加到当前字典
        /// </summary>
        /// <param name="item">指定要添加的键值对</param>
        public void Add(KeyValuePair<Guid, ResourceKey> item)
        {
            lock (m_lock) {
                if (!ContainsKey(item.Key)) {
                    m_resourceKey.Add(item.Key, item.Value);
                }
            }
        }

        /// <summary>
        /// 清空当前字典
        /// </summary>
        public void Clear()
        {
            m_resourceKey.Clear();
        }

        /// <summary>
        /// 获取一个值，该值指示当前字典中是否存在指定的键值对
        /// </summary>
        /// <param name="item">指定要比较的对象</param>
        /// <returns>如果比较的对象存在则返回true否则返回false</returns>
        public bool Contains(KeyValuePair<Guid, ResourceKey> item)
        {
            lock (m_lock) {
                var result = ContainsKey(item.Key);
                if (result) {
                    return item.Value == this[item.Key];
                }
                return false;
            }
        }

        /// <summary>
        /// 获取一个值，该值指示当前字典中是否存在指定的键
        /// </summary>
        /// <param name="key">要对比的键</param>
        /// <returns>如果当前字典存在指定的键，则返回true，否则返回false</returns>
        public bool ContainsKey(Guid key)
        {
            lock (m_lock) {
                return m_resourceKey.ContainsKey(key);
            }
        }

        /// <summary>
        /// not support this method
        /// </summary>
        /// <param name="array"></param>
        /// <param name="arrayIndex"></param>
        public void CopyTo(KeyValuePair<Guid, ResourceKey>[] array, Guid arrayIndex)
        {
            throw new NotSupportedException();
        }

        /// <summary>
        ///  not support this method
        /// </summary>
        /// <param name="array"></param>
        /// <param name="arrayIndex"></param>
        public void CopyTo(KeyValuePair<Guid, ResourceKey>[] array, int arrayIndex)
        {
            throw new NotSupportedException();
        }

        /// <summary>
        /// 获取一个用于遍历当前字典的枚举数
        /// </summary>
        /// <returns>返回一个用于遍历当前字典的枚举数</returns>
        public IEnumerator<KeyValuePair<Guid, ResourceKey>> GetEnumerator()
        {
            return m_resourceKey.GetEnumerator();
        }

        /// <summary>
        /// 移除当前字典中指定键值的内容
        /// </summary>
        /// <param name="key">要移除的键</param>
        /// <returns>如果删除成功则返回true，否则返回false</returns>
        public bool Remove(Guid key)
        {
            lock (m_lock) {
                return m_resourceKey.Remove(key);
            }
        }

        /// <summary>
        /// 移除当前字典中指定键值的内容
        /// </summary>
        /// <param name="item">要移除的键值对</param>
        /// <returns>如果删除成功则返回true，否则返回false</returns>
        public bool Remove(KeyValuePair<Guid, ResourceKey> item)
        {
            return Remove(item.Key);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool TryGetValue(Guid key, out ResourceKey value)
        {
            lock (m_lock) {
                return m_resourceKey.TryGetValue(key, out value);
            }
        }

        /// <summary>
        /// 获取一个用于遍历当前字典的枚举数
        /// </summary>
        /// <returns>返回一个用于遍历当前字典的枚举数</returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return m_resourceKey.GetEnumerator();
        }

        #endregion

        #region Property

        /// <summary>
        /// 获取或设置指定关键字的值
        /// </summary>
        /// <param name="key">指定的值</param>
        /// <returns>返回指定键值的资源键</returns>
        public ResourceKey this[Guid key] {
            get {
                if (ContainsKey(key)) {
                    return m_resourceKey[key];
                }
                return null;
            }
            set {
                if (ContainsKey(key)) {
                    m_resourceKey[key] = value;
                }
                else {
                    m_resourceKey.Add(key, value);
                }
            }
        }

        /// <summary>
        /// 获取一个包含资源键唯一标识符的集合
        /// </summary>
        public ICollection<Guid> Keys {
            get { return m_resourceKey.Keys; }
        }

        /// <summary>
        /// 获取一个包含所有资源值的集合
        /// </summary>
        public ICollection<ResourceKey> Values {
            get { return m_resourceKey.Values; }
        }

        /// <summary>
        /// 获取一个值，该值指示当前的集合的只读性
        /// </summary>
        public bool IsReadOnly {
            get { return false; }
        }

        /// <summary>
        /// 获取当前字典中元素的个数
        /// </summary>
        public int Count {
            get { return m_resourceKey.Count; }
        }

        #endregion

        #region Override

        /// <summary>
        /// 获取与当前对象等价的字符串形式
        /// </summary>
        /// <returns>返回与当前对象等价的字符串形式</returns>
        public override string ToString()
        {
            return $"count:{this.m_resourceKey.Count}";
        }

        /// <summary>
        /// 获取当前对象与指定对象之间的等价性
        /// </summary>
        /// <param name="obj">指定要比较的对象</param>
        /// <returns>如果两个对象之间等价则返回true，否则返回false</returns>
        public override bool Equals(object obj)
        {
            return obj.GetHashCode() == this.GetHashCode();
        }

        /// <summary>
        /// 获取当前对象的哈希值
        /// </summary>
        /// <returns>返回当前对象的哈希值</returns>
        public override int GetHashCode()
        {
            return this.m_lock.GetHashCode() ^ this.m_resourceKey.GetHashCode();
        }

        #endregion
    }
}
